/* (C) Copyright 2024, ZWSOFT Co., LTD.(Guangzhou) All Rights Reserved. */
/** @file DataStruct.hpp
 *  @brief 解析器数据结构
 *  @details 用于存储解析器所需要的各种数据
 */
#pragma once
#include <string>
#include <vector>
#include <map>
#include <unordered_map>
#include <unordered_set>
#include <stack>
#include <iostream>
#include <sstream>
#include <algorithm>
#include <cctype>
#include <regex>
#include <typeindex>
#include <typeinfo>

enum Type {		// 暂未使用枚举类来定义枚举值
	NONE,
	INT,
	LONG,
	CHAR,
	DOUBLE,
	BOOL,
	VOID
};

struct BasicType {
	Type type = NONE;
	std::string value = "0";

	BasicType() {};

	BasicType(const BasicType& other) :type(other.type), value(other.value) {}

	BasicType(const BasicType& other, const std::string& val) {
		type = other.type;
		value = val;
	}

	BasicType(const Type& type) :type(type) {};

	BasicType(const Type& type, const std::string& val) :type(type), value(val) {};

	void set_value(std::string value_) {
		value = value_;
		bool is_digit1 = std::all_of(value.begin(), value.end(), ::isdigit);
		bool is_digit2 = value[0] == '-' && std::all_of(value.begin() + 1, value.end(), ::isdigit);
		bool is_valied = true;
		switch (type) {
		case INT:
			if (is_digit1 || is_digit2)
				break;
			else {
				std::cout << "Error: value " << value << " does not match type INT" << std::endl;
				return;
			}
		case LONG:
			if (is_digit1 || is_digit2)
				break;
			else {
				std::cout << "Error: value " << value << " does not match type LONG" << std::endl;
				return;
			}
		case CHAR:
			if (value.size() == 1)
				break;
			else {
				std::cout << "Error: value " << value << " does not match type CHAR" << std::endl;
				return;
			}
		case DOUBLE:
			if (std::regex_match(value, std::regex(R"([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)")))
				break;
			else {
				std::cout << "Error: value " << value << " does not match type DOUBLE" << std::endl;
				return;
			}
		case BOOL:
			if (value == "true" || value == "false")
				break;
			else {
				std::cout << "Error: value " << value << " does not match type BOOL" << std::endl;
				return;
			}
		case VOID:
			std::cout << "Error: cannot assign value to { void } type" << std::endl;
			return;
		default:
			std::cout << "Error: unknown type" << std::endl;
		}
	}

	BasicType operator+(const BasicType& other) const {
		BasicType result = BasicType(*this);
		if (type == NONE || other.type == NONE) {
			result.type = DOUBLE;
		}
		else if (type == DOUBLE || other.type == DOUBLE) {
			result.type = DOUBLE;
		}
		switch (result.type) {
		case INT:
			result.value = std::to_string(std::stoi(value) + std::stoi(other.value));
			break;
		case LONG:
			result.value = std::to_string(std::stol(value) + std::stol(other.value));
			break;
		case CHAR:
			result.value = std::to_string(std::stoi(value) + std::stoi(other.value));
			break;
		case DOUBLE:
			result.value = std::to_string(std::stod(value) + std::stod(other.value));
			break;
		case BOOL:
			result.value = (value == "true" || other.value == "true") ? "true" : "false";
			break;
		case VOID:
			result.value = "";
			break;
		default:
			std::cout << "Error: unknown type" << std::endl;
			break;
		}
		return result;
	}

	BasicType operator-(const BasicType& other) const {
		BasicType result = BasicType(*this);
		if (type == NONE || other.type == NONE) {
			result.type = DOUBLE;
		}
		else if (type == DOUBLE || other.type == DOUBLE) {
			result.type = DOUBLE;
		}
		switch (result.type) {
		case INT:
			result.value = std::to_string(std::stoi(value) - std::stoi(other.value));
			break;
		case LONG:
			result.value = std::to_string(std::stol(value) - std::stol(other.value));
			break;
		case CHAR:
			result.value = std::to_string(std::stoi(value) - std::stoi(other.value));
			break;
		case DOUBLE:
			result.value = std::to_string(std::stod(value) - std::stod(other.value));
			break;
		case BOOL:
			std::cout << "Error: bool can't do subtraction" << std::endl;
			break;
		case VOID:
			result.value = "";
			break;
		default:
			std::cout << "Error: unknown type" << std::endl;
			break;
		}
		return result;
	}

	BasicType operator*(const BasicType& other) const {
		BasicType result = BasicType(*this);
		if (type == NONE || other.type == NONE) {
			result.type = INT;
		}
		else if (type == DOUBLE || other.type == DOUBLE) {
			result.type = DOUBLE;
		}
		switch (result.type) {
		case INT:
			result.value = std::to_string(std::stoi(value) * std::stoi(other.value));
			break;
		case LONG:
			result.value = std::to_string(std::stol(value) * std::stol(other.value));
			break;
		case CHAR:
			result.value = std::to_string(std::stoi(value) * std::stoi(other.value));
			break;
		case DOUBLE:
			result.value = std::to_string(std::stod(value) * std::stod(other.value));
			break;
		case BOOL:
			result.value = (value == "true" && other.value == "true") ? "true" : "false";
			break;
		case VOID:
			result.value = "";
			break;
		default:
			std::cout << "Error: unknown type" << std::endl;
			break;
		}
		return result;
	}

	BasicType operator/(const BasicType& other) const {
		BasicType result = BasicType(*this);
		if (type == NONE || other.type == NONE) {
			result.type = INT;
		}
		else if (type == DOUBLE || other.type == DOUBLE) {
			result.type = DOUBLE;
		}
		switch (result.type) {
		case INT:
			result.value = std::to_string(std::stod(value) / std::stod(other.value));
			break;
		case LONG:
			result.value = std::to_string(std::stol(value) / std::stol(other.value));
			break;
		case CHAR:
			result.value = std::to_string(std::stoi(value) / std::stoi(other.value));
			break;
		case DOUBLE:
			result.value = std::to_string(std::stod(value) / std::stod(other.value));
			break;
		case BOOL:
			std::cout << "Error: bool value can't calculate'\\'" << std::endl;
			break;
		case VOID:
			result.value = "";
			break;
		default:
			std::cout << "Error: unknown type" << std::endl;
			break;
		}
		return result;
	}
};

struct Variable {
public:
	friend class Params;
	std::string name;
	bool is_const = false;
	std::stack<char> ptr_ref;
private:
	std::shared_ptr<BasicType> ptr;

public:
	Variable() : name(""), ptr(std::make_shared<BasicType>(NONE, "0")) {}

	Variable(std::string name) : name(name), ptr(std::make_shared<BasicType>(NONE, "0")) {}

	Variable(const Type& type, std::string value) : name(""), ptr(std::make_shared<BasicType>(type, value)) {}

	Variable(const Variable& other) {
		name = other.name;
		is_const = other.is_const;
		ptr_ref = other.ptr_ref;
		ptr = other.ptr;
	}

	Variable(const bool is_const, const Type& type, const std::stack<char>& ptr_ref, const std::string& name) {		// 无值构造
		this->name = name;
		this->is_const = is_const;
		this->ptr_ref = ptr_ref;
		this->ptr = std::make_shared<BasicType>(type);
	}

	Variable(const Variable& other, const std::string& val) {			// 参考并赋值
		this->name = other.name;
		this->is_const = other.is_const;
		this->ptr_ref = other.ptr_ref;
		this->ptr = std::make_shared<BasicType>(*other.ptr, val);  // 深拷贝
	}

	Variable copy() {
		Variable copyed_var(*this);
		copyed_var.ptr = std::make_shared<BasicType>(*ptr);
		return copyed_var;
	}

	//~Variable() { delete ptr; }

	std::string get_value() const {
		return ptr->value;
	}

	Type get_type() const {
		return ptr->type;
	}

	bool set_value(const Variable& var) {
		if (is_const && ptr->value != "0") {		// 已经初始化的const变量，不能赋值
			std::cout << "Error: can't change the value of const variable  => ";
			return false;
		}
		if (ptr->type == INT) {
			var.ptr->value = std::to_string((int)std::stod(var.ptr->value));
		}
		if (var.ptr->type == NONE)
			ptr->value = var.ptr->value;
		else
			ptr = var.ptr;
		return true;
	}

	bool set_value(const int var_new, std::stack<char>& l_pre, const std::stack<char>& r_pre, Variable& target) {
		if (is_const && ptr->value != "0") {		// 已经初始化的const变量，不能赋值
			std::cout << "Error: can't change the value of const variable  => ";
			return false;
		}
		else if (ptr_ref.empty() && l_pre.empty() && r_pre.empty() && target.ptr_ref.empty()) {
			if (ptr->type == INT && target.ptr->type == DOUBLE)
				ptr->value = std::to_string((int)std::stod(target.ptr->value));
			else
				ptr->value = target.ptr->value;
		}
		else {
			if (ptr->type == INT && target.ptr->type == DOUBLE)
				target.ptr->value = std::to_string((int)std::stod(target.ptr->value));
			// 左侧，新定义0, 变量自身可能带前缀，但是没有引用和解引用操作
			// 左侧，已定义1，变量自身可能带前缀，还可能有额外的前缀
			if (var_new == 0) {
				l_pre = std::stack<char>();
			}
			else if (var_new != 1) {
				std::cout << "Error: parameter is not a variable => ";
				return false;
			}
			// 1.对左边进行分析
			bool l_is_reference = false;
			bool l_is_val = false;
			int left_ptr_n = this->get_ptr_n(l_pre, l_is_reference, l_is_val);

			// 2.对右边进行分析
			bool r_is_reference = false;
			bool r_is_val = false;
			int right_ptr_n = target.get_ptr_n(r_pre, r_is_reference, r_is_val);

			// 3.过滤非法操作
			if (left_ptr_n == -1 || right_ptr_n == -1) {
				return false;
			}
			else if (l_is_val) {
				std::cout << "Error: cannot assign a value to a right value => ";
				return false;
			}
			else if (left_ptr_n != right_ptr_n) {  // 数据类型不匹配
				std::cout << "Error: type mismatch in two side of { = } => ";
				return false;
			}

			// 4.赋值操作
			if (l_is_reference) {	//左引用
				if (var_new == 0) {		//左引用（new）
					this->ptr = target.ptr;	// 引用右边
				}
				else {					// 左引用（old）
					if (ptr->type == INT && target.ptr->type == DOUBLE)
						this->ptr->value = std::to_string((int)std::stod(target.ptr->value));
					else
						this->ptr->value = target.ptr->value;
				}
			}
			else {	// 左变量
				this->ptr = target.ptr;
			}
		}
		return true;
	}

	void set_type(Type type) {
		this->ptr->type = type;
	}

	int get_ptr_n(const std::stack<char>& pretext, bool& is_reference, bool& is_val) const {  // ==============
		// 根据右边变量及其前缀信息，判断右边的属性
		std::stack<char> ptr_pre = pretext;		// 前缀信息
		std::stack<char> ptr_self = ptr_ref;	// 自身前缀信息
		is_reference = false;
		// 1.右边变量自身指针的层数分析
		int ptr_n = 0;
		while (!ptr_self.empty()) {
			if (ptr_self.top() == '*')
				++ptr_n;
			else
				is_reference = true;  // 自身是一个引用
			ptr_self.pop();
		}
		// 2.右边前缀分析，判断右边整体是否为值，计算最终指针层数
		std::string pretext_str = ""; // 用于记录错误的位置信息
		is_val = false;
		while (!ptr_pre.empty()) {
			char c = ptr_pre.top();
			ptr_pre.pop();
			pretext_str += c;
			if (is_val && c == '&') {
				std::reverse(pretext_str.begin(), pretext_str.end());
				std::cout << "Error: can't get the address of right value: { " << this->name << " = ?" << pretext_str << this->name << " }" << std::endl;
				return -1;
			}
			if (ptr_n > 0 && c == '*') {			// 对指针解引用操作，合法
				is_reference = true;	// 指针被解引用
				ptr_n--;
			}
			else if (ptr_n >= 0 && c == '&') {		// 对指针取址操作，合法，但是会变成左值，左侧为双层指针
				ptr_n++;
				is_val = true;
			}
			else if (ptr_n == 0 && c == '*') {		// 对变量解引用操作，非法，变量不能解引用
				std::reverse(pretext_str.begin(), pretext_str.end());
				std::cout << "Error: variable can't be dereferenced:{ " << this->name << " = ?" << pretext_str << this->name << " }" << std::endl;
				return -1;;
			}
		}
		return ptr_n;
	}

	Variable& operator=(const Variable& other) {  // 赋值运算符，变量相等不能用作赋值，赋值用set_value
		if (this != &other) {
			name = other.name;
			this->is_const = other.is_const;
			this->ptr_ref = other.ptr_ref;
			this->ptr = other.ptr;
		}
		return *this;
	}

	Variable operator+(const Variable& other) const {
		Variable result(*this);
		BasicType ptr_result = *(this->ptr) + *(other.ptr);
		result.ptr = std::make_shared<BasicType>(ptr_result);
		return result;
	}

	Variable operator-(const Variable& other) const {
		Variable result(*this);
		BasicType ptr_result = *(this->ptr) - *(other.ptr);
		result.ptr = std::make_shared<BasicType>(ptr_result);
		return result;
	}

	Variable operator*(const Variable& other) const {
		Variable result(*this);
		BasicType ptr_result = *(this->ptr) * *(other.ptr);
		result.ptr = std::make_shared<BasicType>(ptr_result);
		return result;
	}

	Variable operator/(const Variable& other) const {
		Variable result(*this);
		BasicType ptr_result = *(this->ptr) / *(other.ptr);
		result.ptr = std::make_shared<BasicType>(ptr_result);
		return result;
	}

};

class Params {
public:
	Params() {};

	// 深拷贝构造函数
	Params(const Params& other) {
		for (const auto& pair : other.m_list) {
			m_list[pair.first] = pair.second;
		}
	}

	// 深拷贝赋值运算符
	Params& operator=(const Params& other) {
		if (this != &other) {
			m_list.clear();
			for (const auto& pair : other.m_list) {
				m_list[pair.first] = pair.second;
			}
		}
		return *this;
	}

	Variable& get(std::string name) {
		if (m_list.find(name) != m_list.end())
			return m_list[name];
		else {
			std::cout << "Error: Variable { " << name << " } not found" << std::endl;
			return m_NONE;
		}
	}

	bool exist(const std::string name) {
		return m_list.find(name) != m_list.end();
	}

	std::string add(const Variable& var) {		// 给定一个变量，将它添加到参数列表
		m_list[var.name] = var;
		return var.name;
	}

	std::string add(const Variable& left, const std::stack<char>& ptr_ref_l_pre, const Variable& right) {	// 给定左值，右值，更新左值并添加到参数列表
		// 1.根据右值及其附加信息，判断右值的属性
		std::stack<char> ptr_pre = ptr_ref_l_pre;	// 右值前缀信息
		std::stack<char> ptr_r = right.ptr_ref;		// 右值自身的信息 + ptr_ref_l_pre附加信息
		int right_ptr_n = 0;		// 右值自身指针的层数
		while (!ptr_r.empty()) {
			if (ptr_r.top() == '*')
				++right_ptr_n;
			ptr_r.pop();
		}
		//ptr_r = right.ptr_ref;
		bool is_right_value = false;	// 右值是否为值（数值或者地址值）
		std::string pretext = ""; // 用于记录错误的位置信息
		while (!ptr_pre.empty()) {
			char c = ptr_pre.top();
			ptr_pre.pop();
			pretext += c;
			if (is_right_value && c == '&') {
				std::reverse(pretext.begin(), pretext.end());
				std::cout << "Error: can't get the address of right value: {" << left.name << " = ?" << pretext << right.name << " }" << std::endl;
				return "";
			}
			if (right_ptr_n > 0 && c == '*') {				// 对指针解引用操作，合法
				is_right_value = false;
				right_ptr_n--;
			}
			else if (right_ptr_n >= 0 && c == '&') {		// 对指针取址操作，合法，但是会变成左值
				right_ptr_n++;
				is_right_value = true;
			}
			else if (right_ptr_n == 0 && c == '*') {		// 对变量解引用操作，非法，变量不能解引用
				std::cout << "Error: variable can't be dereferenced" << std::endl;
				return "";
			}
		}
		// 2.根据左值，判断左值的属性
		std::stack<char> ptr_l = left.ptr_ref;	// 左值的信息
		int left_ptr_n = 0;			// 左值是指针的层数，0为普通变量
		bool is_reference = false;  // 左值是引用，否则为指针或普通变量
		while (!ptr_l.empty()) {
			if (ptr_l.top() == '&') {
				if (left_ptr_n == 0)
					is_reference = true;
				else {
					std::cout << "Error: left value can't be pointed to a referance" << std::endl;  // 指针不能指向引用
					return "";
				}
			}
			else if (is_reference) {		// 定义指针的引用
				++left_ptr_n;
			}
			else {		// 定义多层指针
				++left_ptr_n;
			}
			ptr_l.pop();
		}
		if (left_ptr_n != right_ptr_n) {  // 数据类型不匹配
			std::cout << "Error: type mismatch in two side of { = } while setting parameter list." << std::endl;
			return "";
		}
		if (is_reference) {
			if (is_right_value) {	//左引用，右值
				std::cout << "waiting to implementation 01" << std::endl;
			}
			else {					// 左引用，右变量，形如int &a = b;
				m_list[left.name] = left;
				m_list[left.name].ptr = right.ptr; // 将右边的指针指向左边指针所指向的内容，公用同一块数据
			}
		}
		else {
			if (is_right_value) {	// 左变量，右值
				if (left_ptr_n == 1) {	 // 形如int *a = &b;
					m_list[left.name] = left;
					m_list[left.name].ptr = right.ptr; // 将右边的指针指向左边指针所指向的内容，公用同一块数据
				}
				else {
					std::cout << "waiting to implementation 02" << std::endl;
				}
			}
			else {					// 左变量，右变量
				m_list[left.name] = left;
				m_list[left.name].ptr->value = right.ptr->value;
			}
		}
		return left.name;
	}

	size_t size() const {
		return m_list.size();
	}

private:
	Variable m_NONE = Variable();

	std::unordered_map<std::string, Variable> m_list;
};

